home *** CD-ROM | disk | FTP | other *** search
- /* iswait.c
- Wait for a process to finish.
-
- Copyright (C) 1992 Ian Lance Taylor
-
- This file is part of the Taylor UUCP package.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- The author of the program may be contacted at ian@airs.com or
- c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
- */
-
- #include "uucp.h"
-
- #include "uudefs.h"
- #include "sysdep.h"
-
- #include <errno.h>
-
- #if HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #endif
-
- /* We use a typedef wait_status for wait (waitpid, wait4) to put
- results into. We define the POSIX examination functions we need if
- they are not already defined (if they aren't defined, I assume that
- we have a standard wait status). */
-
- #if HAVE_UNION_WAIT
- typedef union wait wait_status;
- #ifndef WIFEXITED
- #define WIFEXITED(u) ((u).w_termsig == 0)
- #endif
- #ifndef WEXITSTATUS
- #define WEXITSTATUS(u) ((u).w_retcode)
- #endif
- #ifndef WTERMSIG
- #define WTERMSIG(u) ((u).w_termsig)
- #endif
- #else /* ! HAVE_UNION_WAIT */
- typedef int wait_status;
- #ifndef WIFEXITED
- #define WIFEXITED(i) (((i) & 0xff) == 0)
- #endif
- #ifndef WEXITSTATUS
- #define WEXITSTATUS(i) (((i) >> 8) & 0xff)
- #endif
- #ifndef WTERMSIG
- #define WTERMSIG(i) ((i) & 0x7f)
- #endif
- #endif /* ! HAVE_UNION_WAIT */
-
- /* Wait for a particular process to finish. The ipid argument should
- be pid_t, but then we couldn't have a prototype. If the zreport
- argument is not NULL, then a wait error will be logged, and if the
- exit status is non-zero it will be logged with zreport as the
- header of the log message. If the zreport argument is NULL, no
- errors will be logged. This function returns the exit status if
- the process exited normally, or -1 on error or if the process was
- killed by a signal (I don't just always return the exit status
- because then the calling code would have to prepared to handle
- union wait status vs. int status, and none of the callers care
- which signal killed the program anyhow).
-
- This functions keeps waiting until the process finished, even if it
- is interrupted by a signal. I think this is right for all uses.
- The controversial one would be when called from uuxqt to wait for a
- requested process. Hitting uuxqt with SIGKILL will approximate the
- actions taken if we return from here with an error anyhow. If we
- do get a signal, we call ulog with a NULL argument to get it in the
- log file at about the right time. */
-
- int
- ixswait (ipid, zreport)
- unsigned long ipid;
- const char *zreport;
- {
- wait_status istat;
-
- #if HAVE_WAITPID
- while (waitpid ((pid_t) ipid, (pointer) &istat, 0) < 0)
- {
- if (errno != EINTR)
- {
- if (zreport != NULL)
- ulog (LOG_ERROR, "waitpid: %s", strerror (errno));
- return -1;
- }
- ulog (LOG_ERROR, (const char *) NULL);
- }
- #else /* ! HAVE_WAITPID */
- #if HAVE_WAIT4
- while (wait4 ((pid_t) ipid, (pointer) &istat, 0,
- (struct rusage *) NULL) < 0)
- {
- if (errno != EINTR)
- {
- if (zreport != NULL)
- ulog (LOG_ERROR, "wait4: %s", strerror (errno));
- return -1;
- }
- ulog (LOG_ERROR, (const char *) NULL);
- }
- #else /* ! HAVE_WAIT4 */
- pid_t igot;
-
- /* We could theoretically get the wrong child here if we're in some
- kind of weird pipeline, so we don't give any error messages for
- it. */
- while ((igot = wait ((pointer) &istat)) != (pid_t) ipid)
- {
- if (igot < 0)
- {
- if (errno != EINTR)
- {
- if (zreport != NULL)
- ulog (LOG_ERROR, "wait: %s", strerror (errno));
- return -1;
- }
- ulog (LOG_ERROR, (const char *) NULL);
- }
- }
- #endif /* ! HAVE_WAIT4 */
- #endif /* ! HAVE_WAITPID */
-
- DEBUG_MESSAGE2 (DEBUG_EXECUTE, "%s %d",
- WIFEXITED (istat) ? "Exit status" : "Signal",
- WIFEXITED (istat) ? WEXITSTATUS (istat) : WTERMSIG (istat));
-
- if (WIFEXITED (istat) && WEXITSTATUS (istat) == 0)
- return 0;
-
- if (zreport != NULL)
- {
- if (! WIFEXITED (istat))
- ulog (LOG_ERROR, "%s: Got signal %d", zreport, WTERMSIG (istat));
- else
- ulog (LOG_ERROR, "%s: Exit status %d", zreport,
- WEXITSTATUS (istat));
- }
-
- if (WIFEXITED (istat))
- return WEXITSTATUS (istat);
- else
- return -1;
- }
-